home *** CD-ROM | disk | FTP | other *** search
/ Freelog 125 / Freelog_MarsAvril2015_No125.iso / Musique / Quod Libet / quodlibet-3.3.0-installer.exe / bin / quodlibet / ext / events / animosd.pyc (.txt) < prev    next >
Python Compiled Bytecode  |  2014-12-31  |  24KB  |  617 lines

  1. # Source Generated with Decompyle++
  2. # File: in.pyc (Python 2.7)
  3.  
  4. from collections import namedtuple
  5. import gi
  6. gi.require_version('PangoCairo', '1.0')
  7. from gi.repository import Gtk, GObject, GLib
  8. from gi.repository import Gdk, GdkPixbuf
  9. from gi.repository import Pango, PangoCairo
  10. import cairo
  11. from math import pi
  12. from quodlibet import config, qltk, app
  13. from quodlibet.qltk.textedit import PatternEdit
  14. from quodlibet.formats import DUMMY_SONG
  15. from quodlibet import parse
  16. from quodlibet.plugins.events import EventPlugin
  17. from quodlibet.plugins import PluginConfigMixin
  18. from quodlibet.util.dprint import print_d, print_w
  19. from quodlibet.util import connect_obj
  20.  
  21. class ConfigLabel(Gtk.Label):
  22.     '''Customised Label for configuration, tied to a widget'''
  23.     
  24.     def __init__(self, text, widget):
  25.         super(Gtk.Label, self).__init__(label = text, use_underline = True)
  26.         self.set_mnemonic_widget(widget)
  27.         self.set_alignment(0, 0.5)
  28.  
  29.  
  30.  
  31. class OSDWindow(Gtk.Window):
  32.     __gsignals__ = {
  33.         'fade-finished': (GObject.SignalFlags.RUN_LAST, None, (bool,)) }
  34.     
  35.     def __init__(self, conf, song):
  36.         Gtk.Window.__init__(self, Gtk.WindowType.POPUP)
  37.         self.set_type_hint(Gdk.WindowTypeHint.NOTIFICATION)
  38.         screen = self.get_screen()
  39.         rgba = screen.get_rgba_visual()
  40.         if rgba is not None:
  41.             self.set_visual(rgba)
  42.         self.conf = conf
  43.         self.iteration_source = None
  44.         self.fading_in = False
  45.         self.fade_start_time = 0
  46.         cover = song.find_cover()
  47.         
  48.         try:
  49.             if cover is not None:
  50.                 cover = GdkPixbuf.Pixbuf.new_from_file(cover.name)
  51.         except GLib.GError:
  52.             gerror = None
  53.             print_w('GDK error while loading cover image: %s' % gerror.message)
  54.         except:
  55.             format_exc = format_exc
  56.             import traceback
  57.             print_w('Error loading cover image: %s' % format_exc())
  58.  
  59.         mgeo = screen.get_monitor_geometry(conf.monitor)
  60.         coverwidth = min(120, mgeo.width // 8)
  61.         textwidth = mgeo.width - 2 * (conf.border + conf.margin)
  62.         if cover is not None:
  63.             textwidth -= coverwidth + conf.border
  64.             coverheight = int(cover.get_height() * float(coverwidth) / cover.get_width())
  65.         else:
  66.             coverheight = 0
  67.         self.cover_pixbuf = cover
  68.         layout = self.create_pango_layout('')
  69.         layout.set_alignment((Pango.Alignment.LEFT, Pango.Alignment.CENTER, Pango.Alignment.RIGHT)[conf.align])
  70.         layout.set_spacing(Pango.SCALE * 7)
  71.         layout.set_font_description(Pango.FontDescription(conf.font))
  72.         
  73.         try:
  74.             layout.set_markup(parse.XMLFromMarkupPattern(conf.string) % song)
  75.         except parse.error:
  76.             layout.set_markup('')
  77.  
  78.         layout.set_width(Pango.SCALE * textwidth)
  79.         layoutsize = layout.get_pixel_size()
  80.         if layoutsize[0] < textwidth:
  81.             layout.set_width(Pango.SCALE * layoutsize[0])
  82.             layoutsize = layout.get_pixel_size()
  83.         self.title_layout = layout
  84.         winw = layoutsize[0] + 2 * conf.border
  85.         if cover is not None:
  86.             winw += coverwidth + conf.border
  87.         winh = max(coverheight, layoutsize[1]) + 2 * conf.border
  88.         self.set_default_size(winw, winh)
  89.         rect = namedtuple('Rect', [
  90.             'x',
  91.             'y',
  92.             'width',
  93.             'height'])
  94.         rect.x = conf.border
  95.         rect.y = (winh - coverheight) // 2
  96.         rect.width = coverwidth
  97.         rect.height = coverheight
  98.         self.cover_rectangle = rect
  99.         winx = int((mgeo.width - winw) * conf.pos_x)
  100.         winx = max(conf.margin, min(mgeo.width - conf.margin - winw, winx))
  101.         winy = int((mgeo.height - winh) * conf.pos_y)
  102.         winy = max(conf.margin, min(mgeo.height - conf.margin - winh, winy))
  103.         self.move(winx + mgeo.x, winy + mgeo.y)
  104.  
  105.     
  106.     def do_draw(self, cr):
  107.         if self.is_composited():
  108.             self.draw_title_info(cr)
  109.         else:
  110.             walloc = self.get_allocation()
  111.             wpos = self.get_position()
  112.             if not getattr(self, '_bg_sf', None):
  113.                 root_win = self.get_root_window()
  114.                 bg_sf = cairo.ImageSurface(cairo.FORMAT_ARGB32, walloc.width, walloc.height)
  115.                 pb = Gdk.pixbuf_get_from_window(root_win, wpos[0], wpos[1], walloc.width, walloc.height)
  116.                 bg_cr = cairo.Context(bg_sf)
  117.                 Gdk.cairo_set_source_pixbuf(bg_cr, pb, 0, 0)
  118.                 bg_cr.paint()
  119.                 self._bg_sf = bg_sf
  120.             if not getattr(self, '_fg_sf', None):
  121.                 fg_sf = cairo.ImageSurface(cairo.FORMAT_ARGB32, walloc.width, walloc.height)
  122.                 fg_cr = cairo.Context(fg_sf)
  123.                 fg_cr.set_source_surface(fg_sf)
  124.                 self.draw_title_info(fg_cr)
  125.                 self._fg_sf = fg_sf
  126.             cr.set_operator(cairo.OPERATOR_SOURCE)
  127.             cr.set_source_surface(self._bg_sf)
  128.             cr.paint()
  129.             cr.set_operator(cairo.OPERATOR_OVER)
  130.             cr.set_source_surface(self._fg_sf)
  131.             cr.paint_with_alpha(self.get_opacity())
  132.  
  133.     
  134.     def rounded_rectangle(cr, x, y, radius, width, height):
  135.         cr.move_to(x + radius, y)
  136.         cr.line_to(x + width - radius, y)
  137.         cr.arc(x + width - radius, y + radius, radius, -90 * pi / 180, 0 * pi / 180)
  138.         cr.line_to(x + width, y + height - radius)
  139.         cr.arc(x + width - radius, y + height - radius, radius, 0 * pi / 180, 90 * pi / 180)
  140.         cr.line_to(x + radius, y + height)
  141.         cr.arc(x + radius, y + height - radius, radius, 90 * pi / 180, 180 * pi / 180)
  142.         cr.line_to(x, y + radius)
  143.         cr.arc(x + radius, y + radius, radius, 180 * pi / 180, 270 * pi / 180)
  144.         cr.close_path()
  145.  
  146.     rounded_rectangle = staticmethod(rounded_rectangle)
  147.     
  148.     def draw_conf_rect(self, cr, x, y, width, height, radius):
  149.         if self.conf.corners != 0:
  150.             self.rounded_rectangle(cr, x, y, radius, width, height)
  151.         else:
  152.             cr.rectangle(x, y, width, height)
  153.  
  154.     
  155.     def draw_title_info(self, cr):
  156.         cr.save()
  157.         do_shadow = self.conf.shadow[0] != -1
  158.         do_outline = self.conf.outline[0] != -1
  159.         self.set_name('osd_bubble')
  160.         qltk.add_css(self, '\n            #osd_bubble {\n                background-color:rgba(0,0,0,0);\n            }\n        ')
  161.         cr.set_operator(cairo.OPERATOR_OVER)
  162.         cr.set_source_rgba(*self.conf.fill)
  163.         radius = min(25, self.conf.corners * min(*self.get_size()))
  164.         self.draw_conf_rect(cr, 0, 0, self.get_size()[0], self.get_size()[1], radius)
  165.         cr.fill()
  166.         if do_outline:
  167.             f = self.conf.fill
  168.             rgba = (f[0] / 1.25, f[1] / 1.25, f[2] / 1.25, f[3] / 2)
  169.             cr.set_source_rgba(*rgba)
  170.             self.draw_conf_rect(cr, 1, 1, self.get_size()[0] - 2, self.get_size()[1] - 2, radius)
  171.             cr.set_line_width(2)
  172.             cr.stroke()
  173.         textx = self.conf.border
  174.         if self.cover_pixbuf is not None:
  175.             rect = self.cover_rectangle
  176.             textx += rect.width + self.conf.border
  177.             pbuf = self.cover_pixbuf
  178.             transmat = cairo.Matrix()
  179.             if do_shadow:
  180.                 cr.set_source_rgba(*self.conf.shadow)
  181.                 self.draw_conf_rect(cr, rect.x + 2, rect.y + 2, rect.width, rect.height, 0.6 * self.conf.corners * rect.width)
  182.                 cr.fill()
  183.             if do_outline:
  184.                 cr.set_source_rgba(*self.conf.outline)
  185.                 self.draw_conf_rect(cr, rect.x, rect.y, rect.width, rect.height, 0.6 * self.conf.corners * rect.width)
  186.                 cr.stroke()
  187.             Gdk.cairo_set_source_pixbuf(cr, pbuf, 0, 0)
  188.             transmat.scale(pbuf.get_width() / float(rect.width), pbuf.get_height() / float(rect.height))
  189.             transmat.translate(-(rect.x), -(rect.y))
  190.             cr.get_source().set_matrix(transmat)
  191.             self.draw_conf_rect(cr, rect.x, rect.y, rect.width, rect.height, 0.6 * self.conf.corners * rect.width)
  192.             cr.fill()
  193.         PangoCairo.update_layout(cr, self.title_layout)
  194.         height = self.title_layout.get_pixel_size()[1]
  195.         texty = (self.get_size()[1] - height) // 2
  196.         if do_shadow:
  197.             cr.set_source_rgba(*self.conf.shadow)
  198.             cr.move_to(textx + 2, texty + 2)
  199.             PangoCairo.show_layout(cr, self.title_layout)
  200.         if do_outline:
  201.             cr.set_source_rgba(*self.conf.outline)
  202.             cr.move_to(textx, texty)
  203.             PangoCairo.layout_path(cr, self.title_layout)
  204.             cr.stroke()
  205.         cr.set_source_rgb(*self.conf.text[:3])
  206.         cr.move_to(textx, texty)
  207.         PangoCairo.show_layout(cr, self.title_layout)
  208.         cr.restore()
  209.  
  210.     
  211.     def fade_in(self):
  212.         self.do_fade_inout(True)
  213.  
  214.     
  215.     def fade_out(self):
  216.         self.do_fade_inout(False)
  217.  
  218.     
  219.     def do_fade_inout(self, fadein):
  220.         fadein = bool(fadein)
  221.         self.fading_in = fadein
  222.         now = GObject.get_current_time()
  223.         fraction = self.get_opacity()
  224.         if not fadein:
  225.             fraction = 1 - fraction
  226.         self.fade_start_time = now - fraction * self.conf.fadetime
  227.         if self.iteration_source is None:
  228.             self.iteration_source = GLib.timeout_add(self.conf.ms, self.fade_iteration_callback)
  229.  
  230.     
  231.     def fade_iteration_callback(self):
  232.         delta = GObject.get_current_time() - self.fade_start_time
  233.         fraction = delta / self.conf.fadetime
  234.         if self.fading_in:
  235.             self.set_opacity(fraction)
  236.         else:
  237.             self.set_opacity(1 - fraction)
  238.         if not self.is_composited():
  239.             self.queue_draw()
  240.         if fraction >= 1:
  241.             self.iteration_source = None
  242.             self.emit('fade-finished', self.fading_in)
  243.             return False
  244.  
  245.  
  246.  
  247. class AnimOsd(EventPlugin, PluginConfigMixin):
  248.     PLUGIN_ID = 'Animated On-Screen Display'
  249.     PLUGIN_NAME = _('Animated On-Screen Display')
  250.     PLUGIN_DESC = _('Display song information on your screen when it changes.')
  251.     PLUGIN_VERSION = '1.3'
  252.     CONFIG_SECTION = 'animosd'
  253.     
  254.     def PluginPreferences(self, parent):
  255.         
  256.         def _AnimOsd__coltofloat(x):
  257.             return x / 65535
  258.  
  259.         
  260.         def _AnimOsd__floattocol(x):
  261.             return int(x * 65535)
  262.  
  263.         
  264.         def cfg_set_tuple(name, t):
  265.             s = ' '.join(map(str, t))
  266.             self.config_set('%s' % name, s)
  267.  
  268.         
  269.         def show_preview():
  270.             preview_song = app.player.song if app.player.song else DUMMY_SONG
  271.             self.plugin_on_song_started(preview_song)
  272.  
  273.         
  274.         def on_button_pressed(x = None, y = (None,)):
  275.             show_preview()
  276.  
  277.         
  278.         def set_text(button):
  279.             color = button.get_color()
  280.             color = map(_AnimOsd__coltofloat, (color.red, color.green, color.blue, 0))
  281.             self.Conf.text = tuple(color)
  282.             cfg_set_tuple('text', self.Conf.text)
  283.             show_preview()
  284.  
  285.         
  286.         def set_fill(button):
  287.             color = button.get_color()
  288.             color = map(_AnimOsd__coltofloat, (color.red, color.green, color.blue, button.get_alpha()))
  289.             self.Conf.fill = tuple(color)
  290.             cfg_set_tuple('fill', self.Conf.fill)
  291.             show_preview()
  292.  
  293.         
  294.         def set_font(button):
  295.             font = button.get_font_name()
  296.             self.config_set('font', font)
  297.             self.Conf.font = font
  298.             show_preview()
  299.  
  300.         
  301.         def change_delay(button):
  302.             value = int(button.get_value() * 1000)
  303.             self.config_set('delay', str(value))
  304.             self.Conf.delay = value
  305.  
  306.         
  307.         def change_monitor(button):
  308.             '''Monitor number config change handler'''
  309.             value = int(button.get_value())
  310.             self.config_set('monitor', str(value))
  311.             self.Conf.monitor = value
  312.             show_preview()
  313.  
  314.         
  315.         def change_position(button):
  316.             value = button.get_active() / 2
  317.             self.config_set('pos_y', str(value))
  318.             self.Conf.pos_y = value
  319.             show_preview()
  320.  
  321.         
  322.         def change_align(button):
  323.             value = button.get_active()
  324.             self.config_set('align', str(value))
  325.             self.Conf.align = value
  326.             show_preview()
  327.  
  328.         
  329.         def change_shadow(button):
  330.             if button.get_active():
  331.                 self.Conf.shadow = (0, 0, 0, self.Conf.fill[3])
  332.             else:
  333.                 self.Conf.shadow = (-1, 0, 0, 0)
  334.             cfg_set_tuple('shadow', self.Conf.shadow)
  335.             show_preview()
  336.  
  337.         
  338.         def change_outline(button):
  339.             if button.get_active():
  340.                 alpha = min(1, self.Conf.fill[3] * 1.25)
  341.                 self.Conf.outline = (0.1, 0.1, 0.1, alpha)
  342.             else:
  343.                 self.Conf.outline = (-1, 0, 0)
  344.             cfg_set_tuple('outline', self.Conf.outline)
  345.             show_preview()
  346.  
  347.         
  348.         def change_rounded(button):
  349.             if button.get_active():
  350.                 self.Conf.corners = 0.14
  351.             else:
  352.                 self.Conf.corners = 0
  353.             self.config_set('corners', str(self.Conf.corners))
  354.             show_preview()
  355.  
  356.         
  357.         def edit_pattern(button):
  358.             w = PatternEdit(button, AnimOsd.ConfDef.string)
  359.             w.set_default_size(520, 260)
  360.             w.text = self.Conf.string
  361.             connect_obj(w.apply, 'clicked', set_string, w)
  362.             w.show()
  363.  
  364.         
  365.         def set_string(window):
  366.             value = window.text
  367.             self.config_set('string', value)
  368.             self.Conf.string = value
  369.             show_preview()
  370.  
  371.         vb = Gtk.VBox(spacing = 6)
  372.         
  373.         def build_display_widget():
  374.             vb2 = Gtk.VBox(spacing = 3)
  375.             hb = Gtk.HBox(spacing = 6)
  376.             monitor_cnt = Gdk.Screen.get_default().get_n_monitors()
  377.             if monitor_cnt > 1:
  378.                 adj = Gtk.Adjustment(value = self.Conf.monitor, lower = 0, upper = monitor_cnt - 1, step_incr = 1)
  379.                 monitor = Gtk.SpinButton(adjustment = adj)
  380.                 monitor.set_numeric(True)
  381.                 monitor.connect('value-changed', change_monitor)
  382.                 l2 = ConfigLabel('_Monitor:', monitor)
  383.                 hb.pack_start(l2, False, True, 0)
  384.                 hb.pack_start(monitor, False, True, 0)
  385.                 vb2.pack_start(hb, True, True, 0)
  386.             else:
  387.                 self.Conf.monitor = 0
  388.             hb = Gtk.HBox(spacing = 6)
  389.             cb = Gtk.ComboBoxText()
  390.             cb.append_text(_('Top of screen'))
  391.             cb.append_text(_('Middle of screen'))
  392.             cb.append_text(_('Bottom of screen'))
  393.             cb.set_active(int(self.Conf.pos_y * 2))
  394.             cb.connect('changed', change_position)
  395.             lbl = ConfigLabel(_('_Position:'), cb)
  396.             hb.pack_start(lbl, False, True, 0)
  397.             hb.pack_start(cb, False, True, 0)
  398.             vb2.pack_start(hb, False, True, 0)
  399.             return vb2
  400.  
  401.         frame = qltk.Frame(label = _('Display'), child = build_display_widget())
  402.         frame.set_border_width(6)
  403.         vb.pack_start(frame, False, True, 0)
  404.         
  405.         def build_text_widget():
  406.             t = Gtk.Table(n_rows = 2, n_columns = 2)
  407.             t.set_col_spacings(6)
  408.             t.set_row_spacings(3)
  409.             font = Gtk.FontButton(show_style = True)
  410.             font.set_font_name(self.Conf.font)
  411.             font.connect('font-set', set_font)
  412.             lbl = ConfigLabel(_('_Font:'), font)
  413.             t.attach(lbl, 0, 1, 0, 1, xoptions = Gtk.AttachOptions.FILL)
  414.             t.attach(font, 1, 2, 0, 1)
  415.             align = Gtk.ComboBoxText()
  416.             align.append_text(_('Left'))
  417.             align.append_text(_('Center'))
  418.             align.append_text(_('Right'))
  419.             align.set_active(self.Conf.align)
  420.             align.connect('changed', change_align)
  421.             lbl = ConfigLabel(_('_Align text:'), align)
  422.             t.attach(lbl, 0, 1, 1, 2, xoptions = Gtk.AttachOptions.FILL)
  423.             t.attach(align, 1, 2, 1, 2)
  424.             return t
  425.  
  426.         frame = qltk.Frame(label = _('Text'), child = build_text_widget())
  427.         frame.set_border_width(6)
  428.         vb.pack_start(frame, False, True, 0)
  429.         
  430.         def build_colors_widget():
  431.             t = Gtk.Table(n_rows = 2, n_columns = 2)
  432.             t.set_col_spacings(6)
  433.             t.set_row_spacings(3)
  434.             b = Gtk.ColorButton(rgba = Gdk.RGBA(*map(_AnimOsd__floattocol, self.Conf.text)))
  435.             l = ConfigLabel(_('_Text:'), b)
  436.             t.attach(l, 0, 1, 0, 1, xoptions = Gtk.AttachOptions.FILL)
  437.             t.attach(b, 1, 2, 0, 1)
  438.             b.connect('color-set', set_text)
  439.             b = Gtk.ColorButton(color = Gdk.Color(*map(_AnimOsd__floattocol, self.Conf.fill[0:3])))
  440.             b.set_use_alpha(True)
  441.             b.set_alpha(_AnimOsd__floattocol(self.Conf.fill[3]))
  442.             b.connect('color-set', set_fill)
  443.             l = ConfigLabel(_('_Fill:'), b)
  444.             t.attach(l, 0, 1, 1, 2, xoptions = Gtk.AttachOptions.FILL)
  445.             t.attach(b, 1, 2, 1, 2)
  446.             return t
  447.  
  448.         f = qltk.Frame(label = _('Colors'), child = build_colors_widget())
  449.         f.set_border_width(6)
  450.         vb.pack_start(f, False, False, 0)
  451.         
  452.         def build_effects_widget():
  453.             vb2 = Gtk.VBox(spacing = 3)
  454.             hb = Gtk.HBox(spacing = 6)
  455.             toggles = [
  456.                 (_('_Shadows'), self.Conf.shadow[0], change_shadow),
  457.                 (_('_Outline'), self.Conf.outline[0], change_outline),
  458.                 (_('Rou_nded Corners'), self.Conf.corners - 1, change_rounded)]
  459.             for label, current, callback in toggles:
  460.                 checkb = Gtk.CheckButton(label = label, use_underline = True)
  461.                 checkb.set_active(current != -1)
  462.                 checkb.connect('toggled', callback)
  463.                 hb.pack_start(checkb, True, True, 0)
  464.             
  465.             vb2.pack_start(hb, True, True, 0)
  466.             hb = Gtk.HBox(spacing = 6)
  467.             timeout = Gtk.SpinButton(adjustment = Gtk.Adjustment.new(self.Conf.delay / 1000, 0, 60, 0.1, 1, 0), climb_rate = 0.1, digits = 1)
  468.             timeout.set_numeric(True)
  469.             timeout.connect('value-changed', change_delay)
  470.             l1 = ConfigLabel(_('_Delay:'), timeout)
  471.             hb.pack_start(l1, False, True, 0)
  472.             hb.pack_start(timeout, False, True, 0)
  473.             vb2.pack_start(hb, False, True, 0)
  474.             return vb2
  475.  
  476.         frame = qltk.Frame(label = _('Effects'), child = build_effects_widget())
  477.         frame.set_border_width(6)
  478.         vb.pack_start(frame, False, True, 0)
  479.         
  480.         def build_buttons_widget():
  481.             hb = Gtk.HBox(spacing = 6)
  482.             edit_button = qltk.Button(_('Ed_it Display Pattern...'), Gtk.STOCK_EDIT)
  483.             edit_button.connect('clicked', edit_pattern)
  484.             hb.pack_start(edit_button, False, True, 0)
  485.             preview_button = Gtk.Button(label = _('Preview'))
  486.             preview_button.connect('button-press-event', on_button_pressed)
  487.             hb.pack_start(preview_button, False, True, 0)
  488.             return hb
  489.  
  490.         vb.pack_start(build_buttons_widget(), False, True, 0)
  491.         return vb
  492.  
  493.     
  494.     class ConfDef(object):
  495.         pos_x = 0.5
  496.         pos_y = 0
  497.         margin = 50
  498.         border = 20
  499.         fadetime = 0.3
  500.         ms = 40
  501.         delay = 2500
  502.         monitor = 0
  503.         font = 'Sans 22'
  504.         text = (0.9, 0.9, 0.9, 0)
  505.         align = 1
  506.         corners = 0
  507.         outline = (-1, 0, 0, 0.2)
  508.         shadow = (-1, 0, 0, 0.1)
  509.         fill = (0.25, 0.25, 0.25, 0.5)
  510.         bcolor = (0, 0, 0, 0.2)
  511.         string = "<album|[b]<album>[/b]<discnumber| - Disc <discnumber>><part| - [b]<part>[/b]><tracknumber| - <tracknumber>>\n>[span weight='bold' size='large']<title>[/span] - <~length><version|\n[small][i]<version>[/i][/small]><~people|\nby <~people>>"
  512.  
  513.     Conf = ConfDef()
  514.     
  515.     def __init__(self):
  516.         self._AnimOsd__current_window = None
  517.         
  518.         def str_to_tuple(s):
  519.             lst = map(float, s.split())
  520.             while len(lst) < 4:
  521.                 lst.append(0)
  522.             return tuple(lst)
  523.  
  524.         config_map = [
  525.             ('text', str_to_tuple),
  526.             ('fill', str_to_tuple),
  527.             ('shadow', str_to_tuple),
  528.             ('outline', str_to_tuple),
  529.             ('bcolor', str_to_tuple),
  530.             ('corners', float),
  531.             ('font', None),
  532.             ('align', int),
  533.             ('delay', int),
  534.             ('monitor', int),
  535.             ('pos_y', float),
  536.             ('string', None)]
  537.         for key, getconv in config_map:
  538.             
  539.             try:
  540.                 default = getattr(self.Conf, key)
  541.             except AttributeError:
  542.                 print_d("Unknown config item '%s'" % key)
  543.  
  544.             
  545.             try:
  546.                 value = self.config_get(key, default)
  547.                 if value is None:
  548.                     continue
  549.             except (config.Error, ValueError):
  550.                 print_d("Couldn't find config item %s" % key)
  551.                 continue
  552.  
  553.             
  554.             try:
  555.                 if getconv is not None:
  556.                     value = getconv(value)
  557.             except Exception:
  558.                 err = None
  559.                 print_d('Error parsing config for %s (%s) - defaulting to %r' % (key, err, default))
  560.                 if default is not None:
  561.                     self.config_set(key, default)
  562.                 
  563.  
  564.             setattr(self.Conf, key, value)
  565.         
  566.  
  567.     
  568.     def plugin_on_song_started(self, song):
  569.         if self._AnimOsd__current_window is not None:
  570.             if self._AnimOsd__current_window.is_composited():
  571.                 self._AnimOsd__current_window.fade_out()
  572.             else:
  573.                 self._AnimOsd__current_window.hide()
  574.                 self._AnimOsd__current_window.destroy()
  575.         if song is None:
  576.             self._AnimOsd__current_window = None
  577.             return None
  578.         window = None(self.Conf, song)
  579.         window.add_events(Gdk.EventMask.BUTTON_PRESS_MASK)
  580.         window.connect('button-press-event', self._AnimOsd__buttonpress)
  581.         window.connect('fade-finished', self._AnimOsd__fade_finished)
  582.         self._AnimOsd__current_window = window
  583.         window.set_opacity(0)
  584.         window.show()
  585.         window.fade_in()
  586.  
  587.     
  588.     def plugin_on_error(self, song, error):
  589.         if self._AnimOsd__current_window is not None:
  590.             self._AnimOsd__current_window.destroy()
  591.             self._AnimOsd__current_window = None
  592.  
  593.     
  594.     def start_fade_out(window):
  595.         window.fade_out()
  596.         return False
  597.  
  598.     start_fade_out = staticmethod(start_fade_out)
  599.     
  600.     def __buttonpress(self, window, event):
  601.         window.hide()
  602.         if self._AnimOsd__current_window is window:
  603.             self._AnimOsd__current_window = None
  604.         window.destroy()
  605.  
  606.     
  607.     def __fade_finished(self, window, fade_in):
  608.         if fade_in:
  609.             GLib.timeout_add(self.Conf.delay, self.start_fade_out, window)
  610.         else:
  611.             window.hide()
  612.             if self._AnimOsd__current_window is window:
  613.                 self._AnimOsd__current_window = None
  614.             GLib.timeout_add(1000, window.destroy)
  615.  
  616.  
  617.